package com.swsc.solarverse.assembler;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.swsc.solarverse.common.Constant;
import com.swsc.solarverse.common.enums.FaultCategoryEnum;
import com.swsc.solarverse.common.util.BizAssert;
import com.swsc.solarverse.common.util.LocalDateTimeUtils;
import com.swsc.solarverse.common.util.RegexUtils;
import com.swsc.solarverse.dao.entity.DefectDO;
import com.swsc.solarverse.model.DefectQueryBO;
import com.swsc.solarverse.model.DefectRepeatSumBO;
import com.swsc.solarverse.model.req.DefectQueryReqVO;
import com.swsc.solarverse.service.IDefectService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author anonymous
 * @Date 2022/7/6 14:38
 * @Version 1.0
 * @Description DefectQueryAssembler
 */
@Component
public class DefectQueryAssembler {
    public final IDefectService defectService;

    public DefectQueryAssembler(IDefectService defectService) {
        this.defectService = defectService;
    }

    public QueryWrapper<DefectDO> getQueryWapper(DefectQueryReqVO reqVo) {
        LocalDateTime irPatrolTimeTemp = null;
        LocalDateTime elPatrolTimeTemp = null;
        LocalDateTime ivPatrolTimeTemp = null;
        LocalDateTime lePatrolTimeTemp = null;
        if (StringUtils.isBlank(reqVo.getPatrolTime())) {
            reqVo.setPatrolStartTime(null);
            reqVo.setPatrolEndTime(null);
            if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IR.getCode())) {
                irPatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.IR.getCode());
            }
            if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.EL.getCode())) {
                elPatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.EL.getCode());
            }
            if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IV.getCode())) {
                ivPatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.IV.getCode());
            }
            if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.LE.getCode())) {
                lePatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.LE.getCode());
            }
        } else {
            String patrolTimeStr = reqVo.getPatrolTime();
            BizAssert.isFalse(!RegexUtils.matchAllDateTime(patrolTimeStr), "巡检时间格式不正确");
            if (RegexUtils.isDate(patrolTimeStr)) {
                patrolTimeStr = patrolTimeStr + " 00:00:00";
            }
            LocalDateTime patrolTime = LocalDateTimeUtils.str2Time(patrolTimeStr);
            reqVo.setPatrolStartTime(LocalDateTimeUtils.getDayStart(patrolTime));
            reqVo.setPatrolEndTime(LocalDateTimeUtils.getDayEnd(patrolTime));
            reqVo.setPatrolTime(null);
        }
        LocalDateTime dealTimeStart = null;
        LocalDateTime dealTimeEnd = null;
        if (StringUtils.isNotBlank(reqVo.getDealTime())) {
            String dealTimeStr = reqVo.getDealTime().substring(0, 10);
            LocalDateTime dealTime = LocalDateTimeUtils.str2Time(dealTimeStr);
            dealTimeStart = LocalDateTimeUtils.getDayStart(dealTime);
            dealTimeEnd = LocalDateTimeUtils.getDayEnd(dealTime);
        }
        List<String> deviceCodeIn = null;
        if (null != reqVo.getRepeatTimes()) {
            List<DefectRepeatSumBO> statisticsDos = defectService.statisticsRepeatDefect(reqVo.map(DefectQueryBO.class));
            if (CollectionUtils.isNotEmpty(statisticsDos)) {
                deviceCodeIn = statisticsDos.stream().map(DefectRepeatSumBO::getDeviceCode).collect(Collectors.toList());
            }
        }

        List<String> fauntNameIn = null;
        if (StringUtils.isNotBlank(reqVo.getFaultNameInStr())) {
            String[] faultNameArr = reqVo.getFaultNameInStr().split(",");
            fauntNameIn = Arrays.asList(faultNameArr);
        }
        List<String> fauntNoIn = null;
        if (StringUtils.isNotBlank(reqVo.getFaultNoInStr())) {
            String[] faultNoArr = reqVo.getFaultNoInStr().split(",");
            fauntNoIn = Arrays.asList(faultNoArr);
        }
        if (CollectionUtils.isEmpty(reqVo.getOrganNoIn()) && null != reqVo.getOrganNo() &&
                !Constant.DEFAULT_SYS_ORGAN_NO.equals(reqVo.getOrganNo())) {
            reqVo.setOrganNoIn(Arrays.asList(reqVo.getOrganNo()));
        }
        LocalDateTime irPatrolTime = irPatrolTimeTemp;
        LocalDateTime elPatrolTime = elPatrolTimeTemp;
        LocalDateTime ivPatrolTime = ivPatrolTimeTemp;
        LocalDateTime lePatrolTime = lePatrolTimeTemp;
        QueryWrapper<DefectDO> queryWrapper = Wrappers.<DefectDO>query();
        queryWrapper.lambda()
                .in(CollectionUtils.isNotEmpty(reqVo.getDefectIdIn()), DefectDO::getId, reqVo.getDefectIdIn())
                .eq(null != reqVo.getTenantNo() && !Constant.DEFAULT_SYS_TENANT_NO.equals(reqVo.getTenantNo()), DefectDO::getTenantNo, reqVo.getTenantNo())
                .in(CollectionUtils.isNotEmpty(reqVo.getOrganNoIn()), DefectDO::getOrganNo, reqVo.getOrganNoIn())
                .like(StringUtils.isNotBlank(reqVo.getDeviceCode()), DefectDO::getDeviceCode, reqVo.getDeviceCode())
                .eq(StringUtils.isNotBlank(reqVo.getFaultName()), DefectDO::getFaultName, reqVo.getFaultName())
                .eq(StringUtils.isNotBlank(reqVo.getFaultNo()), DefectDO::getFaultName, reqVo.getFaultNo())
                .in(CollectionUtils.isNotEmpty(reqVo.getFaultNoIn()), DefectDO::getFaultName, reqVo.getFaultNoIn())
                .in(CollectionUtils.isNotEmpty(fauntNameIn), DefectDO::getFaultName, fauntNameIn)
                // faultNoInStr用faultName查询 app
                .in(CollectionUtils.isNotEmpty(fauntNoIn), DefectDO::getFaultName, fauntNoIn)
                .eq(StringUtils.isNotBlank(reqVo.getFaultStatus()), DefectDO::getState, reqVo.getFaultStatus())
                .in(CollectionUtils.isNotEmpty(deviceCodeIn), DefectDO::getDeviceCode, deviceCodeIn)
                .ge(null != reqVo.getPatrolStartTime(), DefectDO::getPatrolTime, reqVo.getPatrolStartTime())
                .le(null != reqVo.getPatrolEndTime(), DefectDO::getPatrolTime, reqVo.getPatrolEndTime())
                .eq(StringUtils.isNotBlank(reqVo.getZone()), DefectDO::getZone, reqVo.getZone())
                .ge(null != dealTimeStart, DefectDO::getDealTime, dealTimeStart)
                .lt(null != dealTimeEnd, DefectDO::getDealTime, dealTimeEnd)
                .eq(StringUtils.isNotBlank(reqVo.getProcessState()), DefectDO::getProcessState, reqVo.getProcessState())
                .in(DefectDO::getFaultCategory, CollectionUtils.isNotEmpty(reqVo.getFaultCategoryIn()) ? reqVo.getFaultCategoryIn() : FaultCategoryEnum.getFaultCategoryCollectionIR());
        if (CollectionUtils.isNotEmpty(reqVo.getFaultCategoryIn())) {
            if (null != irPatrolTime || null != elPatrolTime || null != ivPatrolTime || null != lePatrolTime) {

                queryWrapper.lambda().and(wr -> {
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IR.getCode()) && null != irPatrolTime) {
                        wr.or(wr1 -> {
                            wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.IR.getCode());
                            wr1.ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(irPatrolTime))
                                    .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(irPatrolTime));
                        });
                    }
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.EL.getCode()) && null != elPatrolTime) {
                        wr.or(wr1 -> wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.EL.getCode())
                                .ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(elPatrolTime))
                                .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(elPatrolTime)));

                    }
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IV.getCode()) && null != ivPatrolTime) {
                        wr.or(wr1 -> wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.IV.getCode())
                                .ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(ivPatrolTime))
                                .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(ivPatrolTime)));
                    }
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.LE.getCode()) && null != lePatrolTime) {
                        wr.or(wr1 -> wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.LE.getCode())
                                .ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(lePatrolTime))
                                .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(lePatrolTime)));
                    }
                });
            }
        }
        ;
        return queryWrapper;
    }

    public LambdaQueryWrapper<DefectDO> getLambdaQueryWapper(DefectQueryReqVO reqVo) {
        LocalDateTime irPatrolTimeTemp = null;
        LocalDateTime elPatrolTimeTemp = null;
        LocalDateTime ivPatrolTimeTemp = null;
        LocalDateTime lePatrolTimeTemp = null;
        if (StringUtils.isBlank(reqVo.getPatrolTime())) {
            /*if (null == reqVo.getPatrolStartTime() && null == reqVo.getPatrolEndTime()) {
                // 如果时间都为空 则获取当前电站的最新时间
                LocalDateTime patrolTime = defectService.maxPatrolTime(reqVo.getOrganNo());
                if (null != patrolTime) {
                    reqVo.setPatrolStartTime(LocalDateTimeUtils.getDayStart(patrolTime));
                    reqVo.setPatrolEndTime(LocalDateTimeUtils.getDayEnd(patrolTime));
                }
            }
            if (null == reqVo.getPatrolStartTime() && null != reqVo.getPatrolEndTime()) {
                // 开始时间为空, 结束时间不为空
                LocalDateTime patrolTime = reqVo.getPatrolEndTime();
                patrolTime = LocalDateTimeUtils.getDayStart(patrolTime);
                reqVo.setPatrolStartTime(patrolTime);
            }
            if (null != reqVo.getPatrolStartTime() && null == reqVo.getPatrolEndTime()) {
                // 开始时间不为空, 结束时间为空
                LocalDateTime patrolTime = reqVo.getPatrolStartTime();
                patrolTime = LocalDateTimeUtils.getDayEnd(patrolTime);
                reqVo.setPatrolEndTime(patrolTime);
            }*/
            if (null != reqVo.getPatrolStartTime() || null != reqVo.getPatrolEndTime()) {
                BizAssert.isFalse(null != reqVo.getPatrolStartTime() &&
                                null != reqVo.getPatrolEndTime() &&
                                reqVo.getPatrolStartTime().compareTo(reqVo.getPatrolEndTime()) > 0,
                        "巡检开始时间和结束时间不正确");
                if (null != reqVo.getPatrolStartTime()) {
                    reqVo.setPatrolStartTime(LocalDateTimeUtils.getDayStart(reqVo.getPatrolStartTime()));
                }
                if (null != reqVo.getPatrolEndTime()) {
                    reqVo.setPatrolEndTime(LocalDateTimeUtils.getDayEnd(reqVo.getPatrolEndTime()));
                }
            } else {
                reqVo.setPatrolStartTime(null);
                reqVo.setPatrolEndTime(null);
                if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IR.getCode())) {
                    irPatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.IR.getCode());
                }
                if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.EL.getCode())) {
                    elPatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.EL.getCode());
                }
                if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IV.getCode())) {
                    ivPatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.IV.getCode());
                }
                if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.LE.getCode())) {
                    lePatrolTimeTemp = defectService.maxCategoryPatrolTime(reqVo.getOrganNo(), FaultCategoryEnum.LE.getCode());
                }
            }
        } else {
            LocalDateTime patrolTime = null;
            if (RegexUtils.isDate(reqVo.getPatrolTime())) {
                patrolTime = LocalDateTimeUtils.str2Time(reqVo.getPatrolTime() + " 00:00:00");
            } else {
                patrolTime = LocalDateTimeUtils.str2Time(reqVo.getPatrolTime());
            }

            reqVo.setPatrolStartTime(LocalDateTimeUtils.getDayStart(patrolTime));
            reqVo.setPatrolEndTime(LocalDateTimeUtils.getDayEnd(patrolTime));
        }
        List<String> deviceCodeIn = null;
        if (null != reqVo.getRepeatTimes()) {
            List<DefectRepeatSumBO> statisticsDos = defectService.statisticsRepeatDefect(reqVo.map(DefectQueryBO.class));
            if (CollectionUtils.isNotEmpty(statisticsDos)) {
                deviceCodeIn = statisticsDos.stream().map(DefectRepeatSumBO::getDeviceCode).collect(Collectors.toList());
            }
        }
        List<String> fauntNameIn = null;
        if (StringUtils.isNotBlank(reqVo.getFaultNameInStr())) {
            String[] faultNameArr = reqVo.getFaultNameInStr().split(",");
            fauntNameIn = Arrays.asList(faultNameArr);
        }
        List<String> fauntNoIn = null;
        if (StringUtils.isNotBlank(reqVo.getFaultNoInStr())) {
            String[] faultNoArr = reqVo.getFaultNoInStr().split(",");
            fauntNoIn = Arrays.asList(faultNoArr);
        }
        LocalDateTime irPatrolTime = irPatrolTimeTemp;
        LocalDateTime elPatrolTime = elPatrolTimeTemp;
        LocalDateTime ivPatrolTime = ivPatrolTimeTemp;
        LocalDateTime lePatrolTime = lePatrolTimeTemp;
        LambdaQueryWrapper<DefectDO> queryWrapper = Wrappers.<DefectDO>lambdaQuery()
                .in(CollectionUtils.isNotEmpty(reqVo.getOrganNoIn()), DefectDO::getOrganNo, reqVo.getOrganNoIn())
                .eq(StringUtils.isNotBlank(reqVo.getDeviceCode()), DefectDO::getDeviceCode, reqVo.getDeviceCode())
                .eq(StringUtils.isNotBlank(reqVo.getFaultName()), DefectDO::getFaultName, reqVo.getFaultName())
                .eq(StringUtils.isNotBlank(reqVo.getFaultNo()), DefectDO::getFaultName, reqVo.getFaultNo())
                .in(CollectionUtils.isNotEmpty(reqVo.getFaultNoIn()), DefectDO::getFaultName, reqVo.getFaultNoIn())
                .in(CollectionUtils.isNotEmpty(fauntNameIn), DefectDO::getFaultName, fauntNameIn)
                // faultNoInStr用名字查询
                .in(CollectionUtils.isNotEmpty(fauntNoIn), DefectDO::getFaultName, fauntNoIn)
                .eq(StringUtils.isNotBlank(reqVo.getFaultStatus()), DefectDO::getState, reqVo.getFaultStatus())
                .in(CollectionUtils.isNotEmpty(deviceCodeIn), DefectDO::getDeviceCode, deviceCodeIn)
                .ge(null != reqVo.getPatrolStartTime(), DefectDO::getPatrolTime, reqVo.getPatrolStartTime())
                .lt(null != reqVo.getPatrolEndTime(), DefectDO::getPatrolTime, reqVo.getPatrolEndTime())
                .eq(StringUtils.isNotBlank(reqVo.getZone()), DefectDO::getZone, reqVo.getZone())
                .eq(StringUtils.isNotBlank(reqVo.getProcessState()), DefectDO::getProcessState, reqVo.getProcessState())
                .in(CollectionUtils.isNotEmpty(reqVo.getFaultCategoryIn()), DefectDO::getFaultCategory, reqVo.getFaultCategoryIn());
        if (CollectionUtils.isNotEmpty(reqVo.getFaultCategoryIn())) {
            if (null != irPatrolTime || null != elPatrolTime || null != ivPatrolTime || null != lePatrolTime) {

                queryWrapper.and(wr -> {
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IR.getCode()) && null != irPatrolTime) {
                        wr.or(wr1 -> {
                            wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.IR.getCode());
                            wr1.ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(irPatrolTime))
                                    .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(irPatrolTime));
                        });
                    }
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.EL.getCode()) && null != elPatrolTime) {
                        wr.or(wr1 -> wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.EL.getCode())
                                .ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(elPatrolTime))
                                .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(elPatrolTime)));

                    }
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.IV.getCode()) && null != ivPatrolTime) {
                        wr.or(wr1 -> wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.IV.getCode())
                                .ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(ivPatrolTime))
                                .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(ivPatrolTime)));
                    }
                    if (reqVo.getFaultCategoryIn().contains(FaultCategoryEnum.LE.getCode()) && null != lePatrolTime) {
                        wr.or(wr1 -> wr1.eq(DefectDO::getFaultCategory, FaultCategoryEnum.LE.getCode())
                                .ge(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayStart(lePatrolTime))
                                .lt(DefectDO::getPatrolTime, LocalDateTimeUtils.getDayEnd(lePatrolTime)));
                    }
                });
            }
        }

        return queryWrapper;
    }

    private void setDefaultPatrolTime(DefectQueryReqVO reqVo) {
        if (StringUtils.isBlank(reqVo.getPatrolTime())) {
            if (null == reqVo.getPatrolStartTime() && null == reqVo.getPatrolEndTime()) {
                // 如果时间都为空 则获取当前电站的最新时间
                LocalDateTime patrolTime = defectService.maxPatrolTime(reqVo.getOrganNo());
                if (null != patrolTime) {
                    reqVo.setPatrolStartTime(LocalDateTimeUtils.getDayStart(patrolTime));
                    reqVo.setPatrolEndTime(LocalDateTimeUtils.getDayEnd(patrolTime));
                }
            }
            if (null == reqVo.getPatrolStartTime() && null != reqVo.getPatrolEndTime()) {
                // 开始时间为空, 结束时间不为空
                LocalDateTime patrolTime = reqVo.getPatrolEndTime();
                patrolTime = LocalDateTimeUtils.getDayStart(patrolTime);
                reqVo.setPatrolStartTime(patrolTime);
            }
            if (null != reqVo.getPatrolStartTime() && null == reqVo.getPatrolEndTime()) {
                // 开始时间不为空, 结束时间为空
                LocalDateTime patrolTime = reqVo.getPatrolStartTime();
                patrolTime = LocalDateTimeUtils.getDayEnd(patrolTime);
                reqVo.setPatrolEndTime(patrolTime);
            }
        } else {
            LocalDateTime patrolTime = null;
            if (RegexUtils.isDate(reqVo.getPatrolTime())) {
                patrolTime = LocalDateTimeUtils.str2Time(reqVo.getPatrolTime() + " 00:00:00");
            } else {
                patrolTime = LocalDateTimeUtils.str2Time(reqVo.getPatrolTime());
            }

            reqVo.setPatrolStartTime(LocalDateTimeUtils.getDayStart(patrolTime));
            reqVo.setPatrolEndTime(LocalDateTimeUtils.getDayEnd(patrolTime));
        }
    }

}
